package com.kevin.mybatis.configuration.datascope.handler;

import com.kevin.mybatis.configuration.datascope.annotation.DataScope;
import com.kevin.mybatis.configuration.datascope.util.DataScopeUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.HexValue;
import net.sf.jsqlparser.statement.select.PlainSelect;
import java.lang.reflect.Method;
import java.util.Objects;

@Slf4j
public abstract class DataScopeHandler {

    /**
     * 获取数据范围 SQL 片段
     *
     * @param plainSelect  查询对象
     * @param whereSegment 查询条件片段
     * @return JSqlParser 条件表达式
     */
    @SneakyThrows(Exception.class)
    public Expression getSqlSegment(PlainSelect plainSelect, String whereSegment) {
        // 待执行 sql where 条件表达式
        Expression where = plainSelect.getWhere();
        if (where == null) {
            where = new HexValue(" 1 = 1 ");
        }
        log.debug("开始进行权限过滤,where:{},mappedStatementId:{}", where, whereSegment);
        // 获取 mapper 名称
        String className = whereSegment.substring(0, whereSegment.lastIndexOf("."));
        // 获取方法名
        String methodName = whereSegment.substring(whereSegment.lastIndexOf(".") + 1);
        // 获取当前 mapper 的方法
        Method[] methods = Class.forName(className).getMethods();
        // 遍历判断 mapper 的所有方法，判断方法上是否有 DataScope 注解
        for (Method m : methods) {
            if (Objects.equals(m.getName(), methodName)) {
                DataScope annotation = m.getAnnotation(DataScope.class);
                if (annotation == null) {
                    return where;
                }
                // 数据范围封装
                return this.setExpression(where, DataScopeUtil.getTableName(plainSelect));
            }
        }
        // 说明无权查看
        where = new HexValue(" 1 = 2 ");
        return where;
    }

    public abstract Expression setExpression(Expression where, String tableName);

}
